#include "Directx.h"

#include "Global.h"

Directx::Directx()
{
	ncmdShow	= NULL;
	_d3d		= NULL;
	_d3ddv		= NULL;
	_backBuffer = NULL;
	_backGround = NULL;
}
Directx::Directx(HINSTANCE hInstance)
{
	_hInstance	= hInstance;
	ncmdShow	= SW_SHOW;
	_d3d		= NULL;
	_d3ddv		= NULL;
	_backBuffer = NULL;
	_backGround = NULL;
}
Directx::~Directx(void)
{
	Release();
}
void Directx:: Init(HINSTANCE hInstance)
{
	_hInstance = hInstance;
	ncmdShow = SW_SHOW;
	_d3d		= NULL;
	_d3ddv		= NULL;
	_backBuffer = NULL;
	_backGround = NULL;
	InitWindow();
	InitDirectx();
	InitSpriteHandler();
	InitKeyBoard();
}
void Directx::InitWindow()
{
	WNDCLASSEX wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_PEN);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = NULL;
	wc.hIconSm = NULL;
	wc.hInstance = _hInstance;
	wc.lpfnWndProc = (WNDPROC)WinProc;
	wc.lpszClassName = "Castle Vania";
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClassEx(&wc);

	//Center screen
	int screenX = GetSystemMetrics(SM_CXSCREEN);
	int screenY = GetSystemMetrics(SM_CYSCREEN);

	int xCtr = (screenX - GAME_WIDTH )/ 2;
	int yCtr = (screenY - GAME_HEIGHT)/ 2;

	_hWnd = CreateWindow("Castle Vania",
		"Castle Vania",
		WS_OVERLAPPEDWINDOW,
		xCtr,
		yCtr,
		GAME_WIDTH,
		GAME_HEIGHT,
		NULL,
		NULL,
		_hInstance,
		NULL);
	if (!_hWnd)
	{
		MessageBoxW(0, L"Can't create window", L"error",MB_OK);
	}
	ShowWindow(_hWnd, SW_SHOWDEFAULT);
	UpdateWindow(_hWnd);
}
void Directx::InitDirectx()
{
	_d3d = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS d3dpp;

	ZeroMemory(&d3dpp,sizeof(d3dpp));
	d3dpp.Windowed = true;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.BackBufferHeight = GAME_HEIGHT;
	d3dpp.BackBufferWidth = GAME_WIDTH;
	d3dpp.hDeviceWindow = _hWnd;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

	if(FAILED(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &_d3ddv)))
		if(FAILED(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, _hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &_d3ddv)))
			if(FAILED(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, _hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &_d3ddv)))
			{
				MessageBoxW(0, L"Can not create device", L"error",MB_OK);
			}
			_d3ddv->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&_backBuffer);
}

void Directx::InitSpriteHandler()
{
	D3DXCreateSprite(_d3ddv, &_spriteHandler);
	_d3ddv->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &_backBuffer);
}

void Directx::InitKeyBoard(){
	HRESULT hResult;
	hResult = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL);
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(1)!", L"error",MB_OK);
		return;
	}

	hResult = di->CreateDevice(GUID_SysKeyboard, &keyboard, NULL);
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(2)!", L"error",MB_OK);
		return;
	}

	hResult = keyboard->SetDataFormat(&c_dfDIKeyboard);
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(3)!", L"error",MB_OK);
		return;
	}

	hResult = keyboard->SetCooperativeLevel(_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(4)!", L"error",MB_OK);
		return;
	}

	DIPROPDWORD		dipdw;
	dipdw.diph.dwSize		=	sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize =	sizeof(DIPROPHEADER);
	dipdw.diph.dwHow		=	DIPH_DEVICE;
	dipdw.diph.dwObj		=	0;
	dipdw.dwData			=	KEYBOARD_BUFFER_SIZE;

	hResult = keyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(5)!", L"error",MB_OK);
		return;
	}

	hResult = keyboard->Acquire();
	if (hResult != DI_OK){
		
		MessageBoxW(0, L"Can't create input(6)!", L"error",MB_OK);
		return;
	}
}

LRESULT CALLBACK Directx::WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default: 
		return DefWindowProc(hWnd, message, wParam,lParam);
	}

	return 0;
}

void Directx::Release(){
	if (_d3ddv!=NULL) _d3ddv->Release();
	if (_d3d!=NULL) _d3d->Release();
}

void Directx::ProcessKeyBoard()
{
	keyboard->GetDeviceState(sizeof(keyStates),keyStates);
	dwElements = KEYBOARD_BUFFER_SIZE;
	keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keyEvents, &dwElements, 0);
}

int Directx::IsKeyDown(int KeyCode){
	return (keyStates[KeyCode] & 0x80) > 0;
}

bool Directx::BeginScene(){

	if(FAILED(_d3ddv->BeginScene()))
		return FALSE;
	_d3ddv->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);
	return TRUE;
}

bool Directx::EndScene(){
	if(FAILED(_d3ddv->EndScene()))
		return FALSE;

	_d3ddv->Present(NULL, NULL, NULL, NULL);
	return TRUE;
}
LPDIRECT3DTEXTURE9 Directx::LoadTextureFromFile(char* path, D3DCOLOR transkey){
	HRESULT hResult = NULL;
	HRESULT hr = NULL;
	LPDIRECT3DTEXTURE9 texture;
	D3DXIMAGE_INFO info;

	D3DXGetImageInfoFromFile(path, &info);
	if (hResult != D3D_OK)
		return NULL;
	
	hResult = D3DXCreateTextureFromFileEx(
		_d3ddv,
		path,
		info.Width,
		info.Height,
		1,
		D3DUSAGE_DYNAMIC,
		D3DFMT_UNKNOWN,
		D3DPOOL_DEFAULT,
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		D3DCOLOR_XRGB(255,0,255), //Loai bo mau nen
		&info,
		NULL,
		&texture
		);

	if (hResult != D3D_OK)
	{
		return NULL;
	}

	return texture;
}